#if !defined(AFX_SCSICOMMAND_H__44459DD6_8D2A_4C1D_B486_9AF92E0A03E1__INCLUDED_)
#define AFX_SCSICOMMAND_H__44459DD6_8D2A_4C1D_B486_9AF92E0A03E1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ScsiCommand.h : header file
//
#include "devioctl.h"
#include "ntddscsi.h"
//#include "aspi.h"
//#include "device.h"
#include <stdio.h>
#include <dbt.h>						// For DeviceChange.
#include <winioctl.h>					// For DeviceIOCtl.
#include "Device.h"

typedef enum 
{	
	NONE=SCSI_IOCTL_DATA_UNSPECIFIED,
	READ=SCSI_IOCTL_DATA_IN,
	WRITE=SCSI_IOCTL_DATA_OUT
}Direction;

typedef struct 
{
    SCSI_PASS_THROUGH_DIRECT spt;
    unsigned char sense[18];
}SPKG;

#define  FILE_DEVICE_SCSI              0x0000001b
#define  IOCTL_SCSI_MINIPORT_IDENTIFY  ((FILE_DEVICE_SCSI << 16) + 0x0501)
//#define  IOCTL_SCSI_MINIPORT 0x0004D008  //  see NTDDSCSI.H for definition
#define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE


//  Valid values for the bCommandReg member of IDEREGS.
#define  IDE_ATAPI_IDENTIFY  0xA1  //  Returns ID sector for ATAPI.
#define  IDE_ATA_IDENTIFY    0xEC  //  Returns ID sector for ATA.

   // The following struct defines the interesting part of the IDENTIFY
   // buffer:
typedef struct _IDSECTOR
{
   USHORT  wGenConfig;
   USHORT  wNumCyls;
   USHORT  wReserved;
   USHORT  wNumHeads;
   USHORT  wBytesPerTrack;
   USHORT  wBytesPerSector;
   USHORT  wSectorsPerTrack;
   USHORT  wVendorUnique[3];
   CHAR    sSerialNumber[20];
   USHORT  wBufferType;
   USHORT  wBufferSize;
   USHORT  wECCSize;
   CHAR    sFirmwareRev[8];
   CHAR    sModelNumber[40];
   USHORT  wMoreVendorUnique;
   USHORT  wDoubleWordIO;
   USHORT  wCapabilities;
   USHORT  wReserved1;
   USHORT  wPIOTiming;
   USHORT  wDMATiming;
   USHORT  wBS;
   USHORT  wNumCurrentCyls;
   USHORT  wNumCurrentHeads;
   USHORT  wNumCurrentSectorsPerTrack;
   ULONG   ulCurrentSectorCapacity;
   USHORT  wMultSectorStuff;
   ULONG   ulTotalAddressableSectors;
   USHORT  wSingleWordDMA;
   USHORT  wMultiWordDMA;
   BYTE    bReserved[128];
} IDSECTOR, *PIDSECTOR;


//typedef struct _SRB_IO_CONTROL
//{
//   ULONG HeaderLength;
//   UCHAR Signature[8];
//   ULONG Timeout;
//   ULONG ControlCode;
//   ULONG ReturnCode;
//   ULONG Length;
//} SRB_IO_CONTROL, *PSRB_IO_CONTROL;


/*static void perror (const char *str)
{ 
	LPVOID lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 
		          FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, (LPTSTR) &lpMsgBuf,
				  0, NULL);
    if (str)
		fprintf (stderr,"%s: %s",str,lpMsgBuf);
    else
		fprintf (stderr,"%s",lpMsgBuf);
    LocalFree(lpMsgBuf);
}*/
/////////////////////////////////////////////////////////////////////////////
// CScsiCommand window

class CScsiCommand
{
public:	
	int DisableMCN(BOOL state);
private:
    char dev[100];
    HANDLE fd;
    SPKG   p;
	HANDLE MCNHandle;
	DWORD BytesReturned;
public:

#define VWIN32_DIOC_DOS_IOCTL 1 
 
typedef struct _DEVIOCTL_REGISTERS 
{ 
    DWORD reg_EBX; 
    DWORD reg_EDX; 
    DWORD reg_ECX; 
    DWORD reg_EAX; 
    DWORD reg_EDI; 
    DWORD reg_ESI; 
    DWORD reg_Flags; 
} DEVIOCTL_REGISTERS, *PDEVIOCTL_REGISTERS; 
 
typedef struct _MID 
{ 
    WORD  midInfoLevel; 
    DWORD midSerialNum; 
    BYTE  midVolLabel[11]; 
    BYTE  midFileSysType[8]; 
} MID, *PMID;
public:
	void CloseAssociateHandle();

	int LockDevice();
	int UnlockDevice();

	BOOL DoIOCTL(PDEVIOCTL_REGISTERS preg);
	BOOL GetMediaID(PMID pmid, UINT nDrive);
	CDevice* CurrentDevice;
    CScsiCommand();
    ~CScsiCommand();
	DWORD bytes;
    int associate (char *file);
    unsigned char &operator[] (size_t i);
    unsigned char &sense(size_t i);
    unsigned char *sense();
    void timeout(int i);
    int sendcommand(Direction dir=NONE, unsigned char *buf=NULL, size_t sz=0);
	int transport(Direction dir=NONE, unsigned char *buf=NULL, size_t sz=0);
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SCSICOMMAND_H__44459DD6_8D2A_4C1D_B486_9AF92E0A03E1__INCLUDED_)

